package com.bruce.asurada.interceptor;


import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import com.bruce.asurada.common.Result;
import com.bruce.asurada.common.constants.TokenConstants;
import com.bruce.asurada.common.dto.UserInfoDto;
import com.bruce.asurada.config.SsoProperties;
import com.bruce.asurada.constants.SSOConstants;
import com.bruce.asurada.util.HttpClientUtil;

import io.micrometer.common.util.StringUtils;

import java.util.Map;

/**
 * WebSocket握手拦截器：在连接建立前验证IM会话令牌
 */
@Slf4j
@Component
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {

    @Resource
    private HttpClientUtil httpClientUtil;
    @Autowired
    private SsoProperties ssoProperties;

    /**
     * 握手前执行：验证令牌
     */
    @Override
    public boolean beforeHandshake(
            ServerHttpRequest request,
            ServerHttpResponse response,
            WebSocketHandler wsHandler,
            Map<String, Object> attributes
    ) throws Exception {
        // 1. 从请求参数中获取令牌（IM会话令牌）
        String imSessionToken = null;
        if (request instanceof ServletServerHttpRequest) {
            HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
            imSessionToken = servletRequest.getParameter(SSOConstants.IM_SESSION_TOKEN_COOKIE_NAME);
        }

        // 2. 令牌为空时拒绝连接
        if (StringUtils.isBlank(imSessionToken)) {
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return false;
        }

        // 3. 调用SSO-Server验证令牌有效性
        try {
            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.add(TokenConstants.IM_SESSION_TOKEN_HEADER_NAME, imSessionToken);

            // 调用验证接口
            Result<UserInfoDto> result = httpClientUtil.get(ssoProperties.getServer().getVerifyImSessionUrl(), headers, new ParameterizedTypeReference<Result<UserInfoDto>>() {});
            if(null == result|| !result.isSuccess()){
                // 验证失败
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return false;
            }

            // 验证通过：存储用户名到会话属性
            UserInfoDto userInfo = result.getData();
            String username = userInfo.getUsername();
            attributes.put("username", username); // 存储用户名供后续使用
            attributes.put(SSOConstants.IM_SESSION_TOKEN_COOKIE_NAME, imSessionToken);       // 存储令牌
            return true;
        } catch (Exception e) {
            // 验证过程异常
            log.error("令牌验证异常: {}", e.getMessage());
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            return false;
        }
    }

    /**
     * 握手后执行：无需处理
     */
    @Override
    public void afterHandshake(
            ServerHttpRequest request,
            ServerHttpResponse response,
            WebSocketHandler wsHandler,
            Exception exception
    ) {
        // 握手完成后不需要额外操作
    }
}
